﻿Public Class Form1
    'Hue,
    '  Saturnation,
    '  Brightness 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim c As Color = fromCMYK(0, 1, 1, 0)

    End Sub

    Private Function toDec(ByVal value As String, ByVal base As String) As Integer
        Dim returnVal As Integer
        For i As Integer = value.Length - 1 To 0 Step -1
            returnVal += base.IndexOf(value(i)) * Math.Pow(base.Length, value.Length - i - 1)
        Next
        Return returnVal
    End Function

    Private Function fromDec(ByVal value As Integer, ByVal base As String) As String
        Dim returnVal As String = ""
        Do Until value = 0
            Dim result As Integer
            Math.DivRem(value, base.Length, result)
            returnVal = base(result) & returnVal
            value = Math.Floor(value / base.Length)
        Loop
        Return returnVal
    End Function



    Const Binary As String = "01"
    Const Decimals As String = "0123456789"
    Const HexaDecimal As String = "0123456789ABCDEF"

    Private Sub tbRGB_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbRed.Scroll, tbGreen.Scroll, tbBlue.Scroll
        GenerateColor(Color.FromArgb(tbRed.Value, tbGreen.Value, tbBlue.Value), ConvertionType.RGB)
    End Sub



    Private Sub GenerateColor(ByVal C As Color, ByVal type As ConvertionType)



        If type <> ConvertionType.RGB Then
            tbRed.Value = C.R
            tbGreen.Value = C.G
            tbBlue.Value = C.B
        End If
        If type <> ConvertionType.HSB Then
            tbHue.Value = C.GetHue
            tbSaturnation.Value = C.GetSaturation * 100
            tbBrightness.Value = C.GetBrightness * 100
        End If


        'RED
        Using Img As New Bitmap(pctRed.Width, pctRed.Height), g As Graphics = Graphics.FromImage(Img)
            For i As Integer = 0 To pctRed.Width
                g.DrawLine(New Pen(Color.FromArgb(i * 255 / pctRed.Width, C.G, C.B), 1), i, 0, i, Img.Height)
            Next
            Dim x As Integer = Math.Round(C.R / 255 * pctRed.Width) - 1
            g.DrawLine(New Pen(Color.Black, 3), x, 0, x, Img.Height)
            pctRed.Image = Img.Clone
        End Using

        'GREEN
        Using Img As New Bitmap(pctGreen.Width, pctGreen.Height), g As Graphics = Graphics.FromImage(Img)
            For i As Integer = 0 To pctGreen.Width
                g.DrawLine(New Pen(Color.FromArgb(C.R, i * 255 / pctGreen.Width, C.B), 1), i, 0, i, Img.Height)
            Next
            Dim x As Integer = Math.Round(C.G / 255 * pctGreen.Width) - 1
            g.DrawLine(New Pen(Color.Black, 3), x, 0, x, Img.Height)
            pctGreen.Image = Img.Clone
        End Using

        'BLUE
        Using Img As New Bitmap(pctBlue.Width, pctBlue.Height), g As Graphics = Graphics.FromImage(Img)
            For i As Integer = 0 To pctBlue.Width
                g.DrawLine(New Pen(Color.FromArgb(C.R, C.G, i * 255 / pctBlue.Width), 1), i, 0, i, Img.Height)
            Next
            Dim x As Integer = Math.Round(C.B / 255 * pctBlue.Width) - 1
            g.DrawLine(New Pen(Color.Black, 3), x, 0, x, Img.Height)
            pctBlue.Image = Img.Clone
        End Using

        'HUE
        Using Img As New Bitmap(pctHue.Width, pctHue.Height), g As Graphics = Graphics.FromImage(Img)
            For i As Integer = 0 To pctHue.Width

                g.DrawLine(New Pen(fromHSB(i * 360 / pctHue.Width, C.GetSaturation, C.GetBrightness), 1), i, 0, i, Img.Height)
            Next
            Dim x As Integer = Math.Round(C.GetHue / 360 * pctHue.Width) - 1
            g.DrawLine(New Pen(Color.Black, 3), x, 0, x, Img.Height)
            pctHue.Image = Img.Clone
        End Using

        'SATURATION
        Using Img As New Bitmap(pctSaturation.Width, pctSaturation.Height), g As Graphics = Graphics.FromImage(Img)
            For i As Integer = 0 To pctSaturation.Width

                g.DrawLine(New Pen(fromHSB(C.GetHue, i / pctSaturation.Width, C.GetBrightness), 1), i, 0, i, Img.Height)
            Next
            Dim x As Integer = Math.Round(C.GetSaturation * pctSaturation.Width) - 1
            g.DrawLine(New Pen(Color.Black, 3), x, 0, x, Img.Height)
            pctSaturation.Image = Img.Clone
        End Using

        'BRIGHTNESS
        Using Img As New Bitmap(pctBrightness.Width, pctBrightness.Height), g As Graphics = Graphics.FromImage(Img)
            For i As Integer = 0 To pctBrightness.Width

                g.DrawLine(New Pen(fromHSB(C.GetHue, C.GetSaturation, i / pctBrightness.Width), 1), i, 0, i, Img.Height)
            Next
            Dim x As Integer = Math.Round(C.GetBrightness * pctBrightness.Width) - 1
            g.DrawLine(New Pen(Color.Black, 3), x, 0, x, Img.Height)
            pctBrightness.Image = Img.Clone
        End Using

        PictureBox1.BackColor = C
    End Sub

    Private Enum ConvertionType
        RGB
        HSB
        CMYK
    End Enum




    Private Function toCMYK(ByVal C As Color) As Collection
        Dim maxRGB As Integer = Max(Max(C.R, C.G), C.B)

        Dim K As Double = 1 - maxRGB / 255



        MsgBox(K)

    End Function


    Private Function fromCMYK(ByVal C As Double, ByVal M As Double, ByVal Y As Double, ByVal K As Double) As Color


        Dim R, G, B As Double



        R = 1 - K
        G = 1 - K
        B = 1 - K

        R -= C
        G -= M
        B -= Y


        If R < 0 Then
            R = 0
        End If
        If G < 0 Then
            G = 0
        End If
        If B < 0 Then
            B = 0
        End If


        Return Color.FromArgb(R * 255, G * 255, B * 255)

    End Function

    Private Function Max(ByVal value1 As Integer, ByVal value2 As Integer) As Integer
        If value1 >= value2 Then
            Return value1
        Else
            Return value2
        End If

    End Function




    Private Function fromHSB(ByVal H As Double, ByVal S As Double, ByVal B As Double) As Color
        If S = 0 Then
            Return Color.FromArgb(Convert.ToInt32(B * 255), Convert.ToInt32(B * 255), Convert.ToInt32(B * 255))
        End If



        Dim fMax, fMid, fMin As Double
        Dim iSextant, iMax, iMid, iMin As Integer

        If (0.5 < B) Then
            fMax = B - (B * S) + S
            fMin = B + (B * S) - S
        Else
            fMax = B + (B * S)
            fMin = B - (B * S)
        End If

        iSextant = Math.Floor(H / 60)
        If (300 <= H) Then
            H -= 360
        End If
        H /= 60
        Dim result As Integer
        Math.DivRem(iSextant + 1, 6, result)

        H -= 2 * Math.Floor(result / 2)

        Math.DivRem(iSextant, 2, result)

        If 0 = result Then
            fMid = H * (fMax - fMin) + fMin
        Else
            fMid = fMin - H * (fMax - fMin)
        End If

        iMax = Convert.ToInt32(fMax * 255)
        iMid = Convert.ToInt32(fMid * 255)
        iMin = Convert.ToInt32(fMin * 255)

        Select Case iSextant
            Case 1
                Return Color.FromArgb(iMid, iMax, iMin)
            Case 2
                Return Color.FromArgb(iMin, iMax, iMid)
            Case 3
                Return Color.FromArgb(iMin, iMid, iMax)
            Case 4
                Return Color.FromArgb(iMid, iMin, iMax)
            Case 5
                Return Color.FromArgb(iMax, iMin, iMid)
            Case Else
                Return Color.FromArgb(iMax, iMid, iMin)
        End Select
    End Function

    Private Sub tbHSB_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbHue.Scroll, tbSaturnation.Scroll, tbBrightness.Scroll
        GenerateColor(fromHSB(tbHue.Value, tbSaturnation.Value / 100, tbBrightness.Value / 100), ConvertionType.HSB)
    End Sub

    Private Sub tbCMYK_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbCyan.Scroll, tbMagneta.Scroll, tbYellow.Scroll, tbKey.Scroll
        GenerateColor(fromCMYK(tbCyan.Value / 100, tbMagneta.Value / 100, tbYellow.Value / 100, tbKey.Value / 100), ConvertionType.CMYK)
    End Sub
End Class









''--------------------------------------------------------------
'' Example of how to call the script "aColor.CMYK_To_RGB" as 
''

'' Get the CMYK values from the user
''
'cmykStringList = MsgBox.MultiInput(
'  "Enter the CMYK value:",
'  "CMYK to RGB conversion",
'  {"C", "M", "Y", "K"},
'  {} )


'' Convert the strings to numbers
''
'cmykNumberList = {}
'for each item in cmykStringList
'  if (item.IsNumber) then 
'    cmykNumberList.Add(item.AsNumber)
'  else
'    MsgBox.Error("Entries must all be numbers","")
'    exit
'  end
'end


'' Call the script to do the conversion
''
'theReturn = av.Run("aColor.CMYK_To_RGB", cmykNumberList)
'if (theReturn.Is(string)) then
'' There was an error!
'  MsgBox.Error(theReturn,"")
'  exit
'end

'R = theReturn.Get(0)
'G = theReturn.Get(1)
'B = theReturn.Get(2)

'MsgBox.Info(
'"CMKY: " +
'cmykStringList.Get(0).AsString ++
'cmykStringList.Get(1).AsString ++
'cmykStringList.Get(2).AsString ++
'cmykStringList.Get(3).AsString + NL +
'"RGB: " +
'R.SetFormat("d").AsString ++ 
'G.SetFormat("d").AsString ++ 
'B.SetFormat("d").AsString, "")

''--------------------------------------------------------------
'' End Script


''--------------------------------------------------------------
' '' @script aColor.CMYK_To_RGB
''
' '' @fileName cmyk2rgb.ave
''
' '' @precis This script will convert color values in
' '' CMYK to the RGB color model.  Both models are based 
' '' on the values obtained from Arc/Info SHOW and COLOREDIT
''
' '' @description This script will convert Cyan, Magenta, Yellow, Black
' '' values into the Red, Green, Blue color model. The algorithm
' '' for this script was sourced from "Computer Graphics Principals
' '' and Practice" (full reference show below).  There is a slight 
' '' variation between the model in the book and the model used
' '' by Arc/Info, so I have adopted the A/I model and noted the 
' '' variations.  From these algorithms, it would be possible to create
' '' a dialog similar to the COLOREDIT dialog in Arc/Info.
''
' '' The CMYK values expected as input must be in the range [0,100]
' '' The RGB values are all output in the range [0,255]
''
'' -----------------------------------------------------------------
' '' @note History: Mark Chilcott - December 1998
''
' '' @note Reference: The algorithm for this script was sourced from:
' '' Computer Graphics - Principles and Practice
' '' Second Edition
' '' Foley, van Dam, Feiner and Hughes
' '' © Addison-Wesley Publishing Company, Inc 
''
''
' '' @note This script was tested for the "Standard" model against a
' '' number of ranges, in ARCPLOT (eg, ArcPlot > show cmyk rgb 255 30 60)
' '' with the correct results being observed.  It was also tested against
' '' ArcPlot COLOREDIT.
' ''
' '' @note The algorithm in the book has a RGB range of [0,1] while 
' '' A/I and ArcView use a range of [0,255].  Simply divide the RGB
' '' values by 255 and use the equations to obtain the correct result.
''
' '' @note The CMYK values in A/I are in the range [0,100] while the
' '' ones in the book are in the range [0,1].  Simply multiply by
''  100 to get the A/I results.
''
' '' @note In COLOREDIT in A/I you will note that by changing the 
' '' RGB or HSV values will not change the K value.  This is reflected
' '' in this script.  Note that the SHOW command in A/I also displays 
' '' this behaviour.  Note also, when the K (black) values is moved in
' '' COLOREDIT, the RGB and HSV values will be affected.  This is also
' '' reflected in this script.
''
'' -----------------------------------------------------------------

'' Get the CMYK values ...
''
' '' @note  The parameter list MUST be a list
' '' of 4 numbers in the range [0,100]
''

'paramList = SELF

''  Make sure there are 4 entries in the list, they are
''  all numbers, and they are in the correct range.  If not
''  then return an appropriate error message.
''

'if (paramList.Count <> 4) then
'  return("Error: Incorrect number of parameters")
'end

'for each item in paramList
'  if (item.Is(Number).Not) then
'    return("Error:  At least one param not a number")
'  end

'  if ( (item < 0) or (item > 100) ) then
'    return("Error:  At least one param was out of range [0,100]")
'  end

'end


'C = paramList.Get(0)
'M = paramList.Get(1)
'Y = paramList.Get(2)
'K = paramlist.Get(3)

'' The standard RGB color model in the book uses the range [0,1] while
'' ArcView stores the values in the range [0,255], so have to convert
''
'' Following from the book
'' Given r,g,b each in range [0-1]
'' Desired:
''  c in [0,100]
''  m in [0,100]
''  y in [0,100]
''  k in [0,100]

' '' For the CMK model:
' '' C = 1 - R
' '' M = 1 - G
' '' Y = 1 - B

' '' For the CMYK model:
' '' K = min(C,M,Y)
' '' C = C - K
' '' M = M - K
' '' Y = Y - K

'' Calculate the Value
'' See note for explanation of variation to
'' book formula to meet what A/I does.  Therefore,
'' from the above:
'' R = (1 - [(C + K)/100]) * 255
'' G = (1 - [(M + K)/100]) * 255
'' B = (1 - [(Y + K)/100]) * 255
'' If the value of (C+K), (M+K) or (Y+K) exceeds 100
'' (which is higher than it should be) then the corresponding
'' R, G or B value will become 0, and the calculation of the
'' remaining values calculated on the above formula, but using
'' the value of K as the difference between max(C,M,Y) and 100
'' in the above formula.  This is the way COLOREDIT seems to work.
'' If say C=M=max and C+K > 100, then both R and G would become 0.

'if ( ((C + K) > 100) or
'     ((M + K) > 100) or
'     ((Y + K) > 100)    ) then
'' Initialise the RGB values
'  R = -99
'  G = -99
'  B = -99

'' Find the max of (C,M,Y)
'  theMax = C.Max(M)
'  theMax = theMax.Max(Y)

'' Set the value of RGB to 0 if it
'' is the max value.
'  if (theMax = C) then
'    R = 0
'  end
'  if (theMax = M) then
'    G = 0
'  end
'  if (theMax = K) then
'    Y = 0
'  end

'' Find the new value for K
'  newK = 100 - theMax

'' Calculate RGB if not already set to 0
'  if (R <> 0) then
'      R = (1 - ((C + newK)/100)) * 255
'  end
'  if (G <> 0) then
'      G = (1 - ((M + newK)/100)) * 255
'  end
'  if (B <> 0) then
'      B = (1 - ((Y + newK)/100)) * 255
'  end

'else
'  R = (1 - ((C + K)/100)) * 255
'  G = (1 - ((M + K)/100)) * 255
'  B = (1 - ((Y + K)/100)) * 255
'end


'returnList = {R, G, B}

'return returnList

'' -------------------------------------------------------------------
'' End Script


'' -------------------------------------------------------------------
'' Example of how to call the script "aColor.RBG_To_CMYK" as 
''

'' Get the RGB values from the user
''
'rgbStringList = MsgBox.MultiInput(
'  "Enter the RGB value:",
'  "RGB to CMYK conversion",
'  {"R", "G", "B"},
'  {} )


'' Convert the strings to numbers
''
'rgbNumberList = {}
'for each item in rgbStringList
'  if (item.IsNumber) then 
'    rgbNumberList.Add(item.AsNumber)
'  else
'    MsgBox.Error("Entries must all be numbers","")
'    exit
'  end
'end


'' Call the script to do the conversion
''
'theReturn = av.Run("aColor.RGB_To_CMYK", rgbNumberList)
'if (theReturn.Is(string)) then
'' There was an error!
'  MsgBox.Error(theReturn,"")
'  exit
'end
'C = theReturn.Get(0)
'M = theReturn.Get(1)
'Y = theReturn.Get(2)
'K = theReturn.Get(3)

'MsgBox.Info(
'"RGB: " +
'rgbStringList.Get(0).AsString ++ 
'rgbStringList.Get(1).AsString ++ 
'rgbStringList.Get(2).AsString + NL +
'"CMKY: " +
'C.SetFormat("d").AsString ++
'M.SetFormat("d").AsString ++
'Y.SetFormat("d").AsString ++
'K.SetFormat("d").AsString, "")
'' -------------------------------------------------------------------
'' End Script



'' -------------------------------------------------------------------
' '' @script aColor.RGB_To_CMYK
''
' '' @fileName rgb2cmyk.ave
''
' '' @precis This script will convert color values in
' '' RGB to the CMY and CMYK color model.
''
' '' @description This script will convert Red, Green, Blue color
' '' values into the Cyan, Magenta, Yellow, Black model. The algorithm
' '' for this script was sourced from "Computer Graphics Principals
' '' and Practice" (full reference show below).  There is a slight 
' '' variation between the model in the book and the model used
' '' by Arc/Info, so I have adopted the A/I model and noted the 
' '' variations.  From these algorithms, it would be possible to create
' '' a dialog similar to the COLOREDIT dialog in Arc/Info.
''
' '' The RGB values expected as input must be in the range [0,255]
' '' The CMYK values are all output in the range [0,100]
''
'' -----------------------------------------------------------------
' '' @note History: Mark Chilcott - December 1998
''
' '' @note Reference: The algorithm for this script was sourced from:

' '' Computer Graphics - Principles and Practice
' '' Second Edition
' '' Foley, van Dam, Feiner and Hughes
' '' © Addison-Wesley Publishing Company, Inc 
''
''
' '' @note This script was tested for the "Standard" model against a
' '' number of ranges, in ARCPLOT (eg, ArcPlot > show cmyk rgb 255 30 60)
' '' with the correct results being observed.  It was also tested against
' '' ArcPlot COLOREDIT.
' ''
' '' @note The algorithm in the book has a RGB range of [0,1] while 
' '' A/I and ArcView use a range of [0,255].  Simply divide the RGB
' '' values by 255 and use the equations to obtain the correct result.
''
' '' @note The CMYK values in A/I are in the range [0,100] while the
' '' ones in the book are in the range [0,1].  Simply multiply by
''  100 to get the A/I results.
''
' '' @note In COLOREDIT in A/I you will note that by changing the 
' '' RGB or HSV values will not change the K value.  This is reflected
' '' in this script.  Note that the SHOW command in A/I also displays 
' '' this behaviour.  Note also, when the K (black) values is moved in
' '' COLOREDIT, the RGB and HSV values will be affected.  This is also
' '' reflected in this script.
''
'' -----------------------------------------------------------------


'' Get the RGB values ...
''
' '' @note  The parameter list MUST be a list
' '' of 3 numbers in the range [0,255]
''
'paramList = SELF

''  Make sure there are 3 entries in the list, they are
''  all numbers, and they are in the correct range.  If not
''  then return an appropriate error message.
''

'if (paramList.Count <> 3) then
'  return("Error: Incorrect number of parameters")
'end

'for each item in paramList
'  if (item.Is(Number).Not) then
'    return("Error:  At least one param not a number")
'  end

'  if ( (item < 0) or (item > 255) ) then
'    return("Error:  At least one param was out of range [0,255]")
'  end
'end


'R = paramList.Get(0)
'G = paramList.Get(1)
'B = paramList.Get(2)


'' Convert the RGB values from the 255 to a fraction in the range [0,1]
'' The standard color model in the book uses the range [0,1] while
'' ArcView stores the values in the range [0,255], so have to convert to
'' the fraction for the formula to work.
''
'redValue = R/255
'greenValue = G/255
'blueValue = B/255

'' Following from the book
'' Given r,g,b each in range [0-1]
'' Desired:
''  c in [0,100]
''  m in [0,100]
''  y in [0,100]
''  k in [0,100]

' '' For the CMK model:
' '' C = 1 - R
' '' M = 1 - G
' '' Y = 1 - B

' '' For the CMYK model:
' '' K = min(C,M,Y)
' '' C = C - K
' '' M = M - K
' '' Y = Y - K


'' Calculate the Value
'' See note for explanation of variation to
'' book formula to meet what A/I does
'cyanValue    = 100*(1 - redValue)
'magentaValue = 100*(1 - greenValue)
'yellowValue  = 100*(1 - blueValue)
'blackValue   = 0

'returnList = {cyanValue, magentaValue, yellowValue, blackValue}

'return returnList

'' -------------------------------------------------------------------
'' End Script


